return TRUE;
}
+/* For local bootc commit, return the base ostree commit that was used to generate the commit.
+ */
+static char *
+get_base_digest_for_bootc_commit (GVariant *commit)
+{
+ g_autoptr (GVariant) metadata = g_variant_get_child_value (commit, 0);
+
+ /* Check for ostree.container.image-config to determine if this is a bootc commit */
+ const char *image_config = NULL;
+ if (!g_variant_lookup (metadata, "ostree.container.image-config", "s", &image_config))
+ return NULL;
+
+ /* If so, since https://github.com/bootc-dev/bootc/pull/1600, the
+ * parent commit will be the base ostree commit. */
+
+ g_autoptr (GVariant) parent_commit_v = g_variant_get_child_value (commit, 1);
+ if (g_variant_n_children (parent_commit_v) != OSTREE_SHA256_DIGEST_LEN)
+ return NULL;
+
+ const guint8 *parent_commit_bin = ot_variant_get_data (parent_commit_v, NULL);
+ if (parent_commit_bin == NULL)
+ return NULL;
+
+ char *basecommit_digest = g_malloc (OSTREE_SHA256_STRING_LEN + 1);
+ ot_bin2hex (basecommit_digest, parent_commit_bin, OSTREE_SHA256_DIGEST_LEN);
+
+ return basecommit_digest;
+}
+
// Given a mount point, directly load the .commit object. At the current time this tool
// doesn't link to libostree.
static gboolean
load_commit_for_deploy (const char *root_mountpoint, const char *deploy_path, GVariant **commit_out,
- GVariant **commitmeta_out, GError **error)
+ GVariant **commitmeta_out, GVariant **basecommit_out,
+ GVariant **basecommitmeta_out, GError **error)
{
g_autofree char *digest = g_path_get_basename (deploy_path);
char *dot = strchr (digest, '.');
g_autoptr (GVariant) commit_v = NULL;
g_autoptr (GVariant) commitmeta_v = NULL;
+ g_autoptr (GVariant) basecommit_v = NULL;
+ g_autoptr (GVariant) basecommitmeta_v = NULL;
if (!load_variant (root_mountpoint, digest, "commit", OSTREE_COMMIT_GVARIANT_FORMAT, FALSE,
&commit_v, error))
&commitmeta_v, error))
return FALSE;
+ /* In case the commit is one created by bootc when importing a container, it will not
+ * be signed. However, we can still look at the base commit which may be signed.
+ */
+ g_autofree char *basecommit_digest = get_base_digest_for_bootc_commit (commit_v);
+ if (basecommit_digest)
+ {
+ if (!load_variant (root_mountpoint, basecommit_digest, "commit",
+ OSTREE_COMMIT_GVARIANT_FORMAT, TRUE, &basecommit_v, error))
+ return FALSE;
+
+ if (basecommit_v != NULL)
+ {
+ if (!load_variant (root_mountpoint, basecommit_digest, "commitmeta",
+ G_VARIANT_TYPE ("a{sv}"), TRUE, &basecommitmeta_v, error))
+ return FALSE;
+ }
+ }
+
*commit_out = g_steal_pointer (&commit_v);
*commitmeta_out = g_steal_pointer (&commitmeta_v);
+ *basecommit_out = g_steal_pointer (&basecommit_v);
+ *basecommitmeta_out = g_steal_pointer (&basecommitmeta_v);
return TRUE;
}
if (rootfs_config->is_signed)
{
const char *composefs_pubkey = rootfs_config->signature_pubkey;
- g_autoptr (GVariant) commit = NULL;
- g_autoptr (GVariant) commitmeta = NULL;
-
- if (!load_commit_for_deploy (root_mountpoint, deploy_path, &commit, &commitmeta,
- error))
+ g_autoptr (GVariant) main_commit = NULL;
+ g_autoptr (GVariant) main_commitmeta = NULL;
+ g_autoptr (GVariant) base_commit = NULL;
+ g_autoptr (GVariant) base_commitmeta = NULL;
+ GVariant *commit = NULL;
+ GVariant *commitmeta = NULL;
+
+ if (!load_commit_for_deploy (root_mountpoint, deploy_path, &main_commit, &main_commitmeta,
+ &base_commit, &base_commitmeta, error))
return glnx_prefix_error (error, "Error loading signatures from repo");
- if (commitmeta == NULL)
+ if (main_commitmeta != NULL)
+ {
+ commit = main_commit;
+ commitmeta = main_commitmeta;
+ }
+ else if (base_commitmeta != NULL)
+ {
+ ot_journal_print (LOG_INFO,
+ "composefs+ostree: Validating composefs using bootc base commit");
+ commit = base_commit;
+ commitmeta = base_commitmeta;
+ }
+ else
return glnx_throw (error, "No commitmeta for deploy %s", deploy_path);
g_autoptr (GVariant) signatures = g_variant_lookup_value (